// 微信小遊戲工具函數庫
// 包含常用的遊戲開發工具函數

/**
 * 工具函數集合
 */
const GameUtils = {
  
  /**
   * 隨機數生成器
   * @param {number} min - 最小值
   * @param {number} max - 最大值
   * @returns {number} 隨機數
   */
  random: function(min, max) {
    return Math.random() * (max - min) + min;
  },
  
  /**
   * 隨機整數生成器
   * @param {number} min - 最小值
   * @param {number} max - 最大值
   * @returns {number} 隨機整數
   */
  randomInt: function(min, max) {
    return Math.floor(Math.random() * (max - min + 1)) + min;
  },
  
  /**
   * 距離計算
   * @param {number} x1 - 第一個點的X座標
   * @param {number} y1 - 第一個點的Y座標
   * @param {number} x2 - 第二個點的X座標
   * @param {number} y2 - 第二個點的Y座標
   * @returns {number} 兩點之間的距離
   */
  distance: function(x1, y1, x2, y2) {
    const dx = x2 - x1;
    const dy = y2 - y1;
    return Math.sqrt(dx * dx + dy * dy);
  },
  
  /**
   * 圓形碰撞檢測
   * @param {Object} circle1 - 第一個圓形對象 {x, y, radius}
   * @param {Object} circle2 - 第二個圓形對象 {x, y, radius}
   * @returns {boolean} 是否碰撞
   */
  circleCollision: function(circle1, circle2) {
    const dist = this.distance(circle1.x, circle1.y, circle2.x, circle2.y);
    return dist < circle1.radius + circle2.radius;
  },
  
  /**
   * 矩形碰撞檢測
   * @param {Object} rect1 - 第一個矩形對象 {x, y, width, height}
   * @param {Object} rect2 - 第二個矩形對象 {x, y, width, height}
   * @returns {boolean} 是否碰撞
   */
  rectCollision: function(rect1, rect2) {
    return rect1.x < rect2.x + rect2.width &&
           rect1.x + rect1.width > rect2.x &&
           rect1.y < rect2.y + rect2.height &&
           rect1.y + rect1.height > rect2.y;
  },
  
  /**
   * 圓形與矩形碰撞檢測
   * @param {Object} circle - 圓形對象 {x, y, radius}
   * @param {Object} rect - 矩形對象 {x, y, width, height}
   * @returns {boolean} 是否碰撞
   */
  circleRectCollision: function(circle, rect) {
    // 找到矩形上距離圓心最近的點
    const closestX = Math.max(rect.x, Math.min(circle.x, rect.x + rect.width));
    const closestY = Math.max(rect.y, Math.min(circle.y, rect.y + rect.height));
    
    // 計算圓心到最近點的距離
    const distance = this.distance(circle.x, circle.y, closestX, closestY);
    
    return distance < circle.radius;
  },
  
  /**
   * 角度計算（弧度）
   * @param {number} x1 - 起點X座標
   * @param {number} y1 - 起點Y座標
   * @param {number} x2 - 終點X座標
   * @param {number} y2 - 終點Y座標
   * @returns {number} 角度（弧度）
   */
  angle: function(x1, y1, x2, y2) {
    return Math.atan2(y2 - y1, x2 - x1);
  },
  
  /**
   * 角度轉弧度
   * @param {number} degrees - 角度
   * @returns {number} 弧度
   */
  toRadians: function(degrees) {
    return degrees * Math.PI / 180;
  },
  
  /**
   * 弧度轉角度
   * @param {number} radians - 弧度
   * @returns {number} 角度
   */
  toDegrees: function(radians) {
    return radians * 180 / Math.PI;
  },
  
  /**
   * 限制數值範圍
   * @param {number} value - 要限制的值
   * @param {number} min - 最小值
   * @param {number} max - 最大值
   * @returns {number} 限制後的值
   */
  clamp: function(value, min, max) {
    return Math.min(Math.max(value, min), max);
  },
  
  /**
   * 線性插值
   * @param {number} a - 起始值
   * @param {number} b - 結束值
   * @param {number} t - 插值因子 (0-1)
   * @returns {number} 插值結果
   */
  lerp: function(a, b, t) {
    return a + (b - a) * t;
  },
  
  /**
   * 顏色轉換工具
   */
  Color: {
    /**
     * 十六進制顏色轉RGB
     * @param {string} hex - 十六進制顏色值
     * @returns {Object} RGB對象 {r, g, b}
     */
    hexToRgb: function(hex) {
      const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
      return result ? {
        r: parseInt(result[1], 16),
        g: parseInt(result[2], 16),
        b: parseInt(result[3], 16)
      } : null;
    },
    
    /**
     * RGB轉十六進制顏色
     * @param {number} r - 紅色值 (0-255)
     * @param {number} g - 綠色值 (0-255)
     * @param {number} b - 藍色值 (0-255)
     * @returns {string} 十六進制顏色值
     */
    rgbToHex: function(r, g, b) {
      return "#" + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1);
    },
    
    /**
     * 生成隨機顏色
     * @returns {string} 隨機十六進制顏色值
     */
    random: function() {
      return this.rgbToHex(
        Math.floor(Math.random() * 256),
        Math.floor(Math.random() * 256),
        Math.floor(Math.random() * 256)
      );
    }
  },
  
  /**
   * 音效管理工具
   */
  Audio: {
    /**
     * 播放音效
     * @param {string} src - 音頻文件路徑
     * @param {boolean} loop - 是否循環播放
     */
    play: function(src, loop = false) {
      try {
        const audio = wx.createInnerAudioContext();
        audio.src = src;
        audio.loop = loop;
        audio.play();
        return audio;
      } catch (error) {
        console.warn('音頻播放失敗:', error);
        return null;
      }
    },
    
    /**
     * 停止音效
     * @param {Object} audio - 音頻對象
     */
    stop: function(audio) {
      if (audio) {
        audio.stop();
        audio.destroy();
      }
    }
  },
  
  /**
   * 本地存儲工具
   */
  Storage: {
    /**
     * 保存數據
     * @param {string} key - 鍵名
     * @param {any} value - 值
     */
    set: function(key, value) {
      try {
        wx.setStorageSync(key, value);
      } catch (error) {
        console.warn('存儲數據失敗:', error);
      }
    },
    
    /**
     * 獲取數據
     * @param {string} key - 鍵名
     * @param {any} defaultValue - 默認值
     * @returns {any} 存儲的值
     */
    get: function(key, defaultValue = null) {
      try {
        const value = wx.getStorageSync(key);
        return value !== '' ? value : defaultValue;
      } catch (error) {
        console.warn('獲取數據失敗:', error);
        return defaultValue;
      }
    },
    
    /**
     * 刪除數據
     * @param {string} key - 鍵名
     */
    remove: function(key) {
      try {
        wx.removeStorageSync(key);
      } catch (error) {
        console.warn('刪除數據失敗:', error);
      }
    },
    
    /**
     * 清空所有數據
     */
    clear: function() {
      try {
        wx.clearStorageSync();
      } catch (error) {
        console.warn('清空數據失敗:', error);
      }
    }
  },
  
  /**
   * 動畫工具
   */
  Animation: {
    /**
     * 緩動函數
     */
    Easing: {
      // 線性
      linear: function(t) { return t; },
      
      // 二次緩入
      easeInQuad: function(t) { return t * t; },
      
      // 二次緩出
      easeOutQuad: function(t) { return t * (2 - t); },
      
      // 二次緩入緩出
      easeInOutQuad: function(t) { 
        return t < 0.5 ? 2 * t * t : -1 + (4 - 2 * t) * t; 
      },
      
      // 三次緩入
      easeInCubic: function(t) { return t * t * t; },
      
      // 三次緩出
      easeOutCubic: function(t) { return (--t) * t * t + 1; },
      
      // 三次緩入緩出
      easeInOutCubic: function(t) { 
        return t < 0.5 ? 4 * t * t * t : (t - 1) * (2 * t - 2) * (2 * t - 2) + 1; 
      }
    },
    
    /**
     * 創建動畫
     * @param {Object} options - 動畫選項
     * @param {number} options.duration - 動畫持續時間（毫秒）
     * @param {Function} options.easing - 緩動函數
     * @param {Function} options.onUpdate - 更新回調
     * @param {Function} options.onComplete - 完成回調
     */
    create: function(options) {
      const startTime = Date.now();
      const duration = options.duration || 1000;
      const easing = options.easing || this.Easing.linear;
      const onUpdate = options.onUpdate || function() {};
      const onComplete = options.onComplete || function() {};
      
      function animate() {
        const elapsed = Date.now() - startTime;
        const progress = Math.min(elapsed / duration, 1);
        const easedProgress = easing(progress);
        
        onUpdate(easedProgress);
        
        if (progress < 1) {
          requestAnimationFrame(animate);
        } else {
          onComplete();
        }
      }
      
      animate();
    }
  },
  
  /**
   * 粒子系統工具
   */
  Particle: {
    /**
     * 創建粒子
     * @param {Object} options - 粒子選項
     * @returns {Object} 粒子對象
     */
    create: function(options) {
      return {
        x: options.x || 0,
        y: options.y || 0,
        vx: options.vx || 0,
        vy: options.vy || 0,
        life: options.life || 100,
        maxLife: options.life || 100,
        color: options.color || '#FFFFFF',
        size: options.size || 2,
        gravity: options.gravity || 0,
        friction: options.friction || 0.98,
        update: function() {
          this.x += this.vx;
          this.y += this.vy;
          this.vy += this.gravity;
          this.vx *= this.friction;
          this.vy *= this.friction;
          this.life--;
        },
        draw: function(ctx) {
          const alpha = this.life / this.maxLife;
          ctx.save();
          ctx.globalAlpha = alpha;
          ctx.fillStyle = this.color;
          ctx.beginPath();
          ctx.arc(this.x, this.y, this.size, 0, Math.PI * 2);
          ctx.fill();
          ctx.restore();
        }
      };
    }
  }
};

// 導出工具函數
if (typeof module !== 'undefined' && module.exports) {
  module.exports = GameUtils;
} else {
  // 在微信小遊戲環境中，將工具函數掛載到全局
  window.GameUtils = GameUtils;
} 
// 微信小遊戲主文件 - 多球回合制彈球遊戲
// 引入工具函數庫
// 注意：在實際項目中，需要確保 utils.js 在 game.js 之前加載

// 遊戲狀態管理
const gameState = {
  canvas: null,           // 畫布對象
  ctx: null,              // 繪圖上下文
  balls: [],              // 小球陣列（多球）
  ballRadius: 10,         // 小球半徑
  ballColor: '#FF6B6B',   // 小球顏色
  ballsToFire: 1,         // 本回合要發射的小球數
  ballsFired: 0,          // 已發射小球數
  ballsReturned: 0,       // 已回收小球數
  fireInterval: 80,       // 小球發射間隔（毫秒）
  isAiming: false,        // 是否正在瞄準
  aimStart: null,         // 瞄準起點
  aimEnd: null,           // 瞄準終點
  fireAngle: Math.PI / 2, // 發射角度（弧度）
  fireReady: true,        // 是否可以發射
  firePos: { x: 0, y: 0 },// 發射起點
  // 其餘狀態保持不變...
  paddle: {
    x: 150,
    y: 550,
    width: 100,
    height: 10,
    color: '#4ECDC4'
  },
  blocks: [],
  score: 0,
  lives: 3,
  gameRunning: false,
  blockRows: 5,
  blockCols: 8,
  blockWidth: 60,
  blockHeight: 20,
  blockPadding: 10,
  launchTime: 0,         // 發射開始時間
  isFastForward: false,  // 是否加速中
  designWidth: 375,      // 設計畫布寬度（iPhone 12/13 mini）
  designHeight: 667,     // 設計畫布高度
  scale: 1,              // 畫布縮放比例
  nextFireX: null, // 下回合發射點 x 座標
};

// 粒子特效管理
const particles = [];

// 產生爆炸粒子
function createExplosion(x, y, color) {
  for (let i = 0; i < 12; i++) {
    particles.push(GameUtils.Particle.create({
      x: x,
      y: y,
      vx: GameUtils.random(-2, 2),
      vy: GameUtils.random(-2, 2),
      life: 20,
      color: color,
      size: GameUtils.random(2, 4),
      gravity: 0.1
    }));
  }
}

// 更新與渲染粒子
function updateParticles(ctx) {
  for (let i = particles.length - 1; i >= 0; i--) {
    const p = particles[i];
    p.update();
    p.draw(ctx);
    if (p.life <= 0) {
      particles.splice(i, 1);
    }
  }
}

// 音效資源（請將音效文件放在合適目錄，這裡用佔位路徑）
const SOUND_HIT = 'audio/hit.mp3';      // 擊中磚塊音效
const SOUND_BREAK = 'audio/break.mp3';  // 磚塊消失音效
const SOUND_FAIL = 'audio/fail.mp3';    // 遊戲結束音效

// 定義貓臉模板（1為有磚塊，0為空）
const CAT_FACE_TEMPLATE = [
  [0,1,0,0,0,0,1,0],
  [1,1,1,1,1,1,1,1],
  [1,0,1,1,1,1,0,1],
  [1,1,1,1,1,1,1,1],
  [0,1,1,1,1,1,1,0]
];
// 新增狗臉模板（高度6格）
const DOG_FACE_TEMPLATE = [
  [0,0,1,1,1,1,0,0],
  [0,1,1,1,1,1,1,0],
  [1,1,0,1,1,0,1,1],
  [1,1,1,1,1,1,1,1],
  [0,1,1,1,1,1,1,0],
  [0,0,1,1,1,1,0,0]
];
const ANIMAL_TEMPLATES = [CAT_FACE_TEMPLATE, DOG_FACE_TEMPLATE];

// 最高分本地存儲key
const BEST_SCORE_KEY = 'block_game_best_score';

// 失敗虛線Y座標（距底部60px，原40+20）
const FAIL_LINE_Y = () => gameState.canvas.height - 60 * gameState.scale;

// 判斷指定格子是否已有方塊
function isBlockAt(x, y, size) {
  return gameState.blocks.some(block =>
    block.visible && Math.abs(block.x - x) < 1 && Math.abs(block.y - y) < 1 && Math.abs(block.width - size) < 1 && Math.abs(block.height - size) < 1
  );
}
// 判斷指定格子(row, col)是否已有方塊
function isGridOccupied(row, col, gridMap) {
  return gridMap.has(`${row},${col}`);
}
// 根據現有方塊生成格子佔用表
function getOccupiedGridMap(blocks, tRows, tCols, blockSize, blockPadding, startX, startY) {
  const map = new Set();
  blocks.forEach(block => {
    // 計算該方塊對應的(row, col)
    const col = Math.round((block.x - startX) / (blockSize + blockPadding));
    const row = Math.round((block.y - startY) / (blockSize + blockPadding));
    if (row >= 0 && row < tRows && col >= 0 && col < tCols) {
      map.add(`${row},${col}`);
    }
  });
  return map;
}

// 初始化遊戲時自動適配畫布和元素
function initGame() {
  console.log('遊戲初始化開始...');
  gameState.canvas = wx.createCanvas();
  gameState.ctx = gameState.canvas.getContext('2d');
  const systemInfo = wx.getSystemInfoSync();
  gameState.canvas.width = systemInfo.windowWidth;
  gameState.canvas.height = systemInfo.windowHeight;
  // 計算縮放比例
  gameState.scale = Math.min(
    systemInfo.windowWidth / gameState.designWidth,
    systemInfo.windowHeight / gameState.designHeight
  );
  // 根據縮放比例調整元素尺寸
  gameState.blockWidth = 60 * gameState.scale;
  gameState.blockHeight = 20 * gameState.scale;
  gameState.blockPadding = 10 * gameState.scale;
  gameState.paddle.width = 100 * gameState.scale;
  gameState.paddle.height = 10 * gameState.scale;
  gameState.paddle.x = (gameState.canvas.width - gameState.paddle.width) / 2;
  gameState.paddle.y = gameState.canvas.height - 50 * gameState.scale;
  gameState.ballRadius = 10 * gameState.scale;
  gameState.firePos.x = gameState.canvas.width / 2;
  gameState.firePos.y = gameState.canvas.height - 30 * gameState.scale;
  initBlocks();
  resetBalls();
  setupTouchEvents();
  gameState.gameRunning = true;
  gameLoop();
  console.log('遊戲初始化完成');
}

// 修改 resetBalls，重置 _returned 和 targetX
function resetBalls() {
  gameState.balls = [];
  for (let i = 0; i < gameState.ballsToFire; i++) {
    gameState.balls.push({
      x: gameState.firePos.x,
      y: gameState.firePos.y,
      dx: 0,
      dy: 0,
      moving: false,
      color: gameState.ballColor,
      _returned: false,
      targetX: undefined
    });
  }
  gameState.ballsFired = 0;
  gameState.ballsReturned = 0;
  gameState.fireReady = true;
}

// 設置觸摸事件（支持瞄準虛線和角度發射）
function setupTouchEvents() {
  wx.onTouchStart((event) => {
    if (!gameState.fireReady) return;
    const touch = event.touches[0];
    gameState.isAiming = true;
    // 起點始終為發射點 firePos
    gameState.aimStart = { x: gameState.firePos.x, y: gameState.firePos.y };
    gameState.aimEnd = { x: touch.clientX, y: touch.clientY };
  });
  wx.onTouchMove((event) => {
    if (!gameState.isAiming) return;
    const touch = event.touches[0];
    // 終點為當前觸點
    gameState.aimEnd = { x: touch.clientX, y: touch.clientY };
  });
  wx.onTouchEnd(() => {
    if (!gameState.isAiming) return;
    gameState.isAiming = false;
    // 計算發射角度（從發射點到拖動方向）
    const dx = gameState.aimEnd.x - gameState.aimStart.x;
    const dy = gameState.aimEnd.y - gameState.aimStart.y;
    let angle = Math.atan2(dy, dx);
    // 限制發射角度（只允許向上）
    if (angle > -0.1) angle = -0.1;
    if (angle < -Math.PI + 0.1) angle = -Math.PI + 0.1;
    gameState.fireAngle = angle;
    // 發射小球
    if (gameState.fireReady) {
      fireBalls();
    }
  });
}

// 修改 fireBalls，發射時記錄時間並重置加速狀態
function fireBalls() {
  gameState.fireReady = false;
  gameState.ballsFired = 0;
  gameState.launchTime = Date.now(); // 發射時記錄時間
  gameState.isFastForward = false;   // 重置加速狀態
  // 發射前重置所有小球速度，防止多次加速疊加
  for (let i = 0; i < gameState.balls.length; i++) {
    gameState.balls[i].dx = 0;
    gameState.balls[i].dy = 0;
    gameState.balls[i].moving = false;
  }
  for (let i = 0; i < gameState.balls.length; i++) {
    setTimeout(() => {
      const speed = 7 * gameState.scale;
      gameState.balls[i].dx = Math.cos(gameState.fireAngle) * speed;
      gameState.balls[i].dy = Math.sin(gameState.fireAngle) * speed;
      gameState.balls[i].moving = true;
      gameState.ballsFired++;
    }, i * gameState.fireInterval);
  }
}

// 優化後的小球與磚塊碰撞檢測
function ballBlockCollision(ball, block) {
  // 找到矩形上距離圓心最近的點
  const closestX = Math.max(block.x, Math.min(ball.x, block.x + block.width));
  const closestY = Math.max(block.y, Math.min(ball.y, block.y + block.height));
  // 計算圓心到最近點的距離
  const dist = GameUtils.distance(ball.x, ball.y, closestX, closestY);
  if (dist < gameState.ballRadius) { // 這裡改成 gameState.ballRadius
    // 判斷撞擊的是哪個邊
    const overlapLeft = Math.abs(ball.x - block.x);
    const overlapRight = Math.abs(ball.x - (block.x + block.width));
    const overlapTop = Math.abs(ball.y - block.y);
    const overlapBottom = Math.abs(ball.y - (block.y + block.height));
    const minOverlap = Math.min(overlapLeft, overlapRight, overlapTop, overlapBottom);
    if (minOverlap === overlapLeft || minOverlap === overlapRight) {
      ball.dx = -ball.dx; // 左右反彈
    } else {
      ball.dy = -ball.dy; // 上下反彈
    }
    return true;
  }
  return false;
}

// 修改 updateGame，實現小球落底後橫向滾動歸位
function updateGame() {
  // 判斷是否需要加速
  if (!gameState.isFastForward && !gameState.fireReady && gameState.launchTime > 0) {
    const elapsed = (Date.now() - gameState.launchTime) / 1000;
    const anyMoving = gameState.balls.some(ball => ball.moving);
    if (elapsed > 6 && anyMoving) {
      gameState.isFastForward = true;
      // 將所有運動中的小球速度加大
      gameState.balls.forEach(ball => {
        if (ball.moving) {
          ball.dx *= 3;
          ball.dy *= 3;
        }
      });
    }
  }
  gameState.balls.forEach(ball => {
    if (ball.moving) {
      ball.x += ball.dx;
      ball.y += ball.dy;
      // 撞牆反彈
      if (ball.x + gameState.ballRadius > gameState.canvas.width || ball.x - gameState.ballRadius < 0) {
        ball.dx = -ball.dx;
        ball.x = GameUtils.clamp(ball.x, gameState.ballRadius, gameState.canvas.width - gameState.ballRadius);
      }
      if (ball.y - gameState.ballRadius < 0) {
        ball.dy = -ball.dy;
        ball.y = gameState.ballRadius;
      }
      // 落到底部
      if (ball.y + gameState.ballRadius > gameState.canvas.height) {
        ball.moving = false;
        // 第一顆落底小球
        if (gameState.nextFireX === null) {
          gameState.nextFireX = ball.x;
          ball.x = gameState.nextFireX;
          ball.y = gameState.canvas.height - gameState.ballRadius;
          if (!ball._returned) {
            gameState.ballsReturned++;
            ball._returned = true;
          }
        } else {
          // 其餘小球設置目標歸位點
          ball.targetX = gameState.nextFireX;
          ball.y = gameState.canvas.height - gameState.ballRadius;
        }
      }
      // 優化後的碰撞檢測
      gameState.blocks.forEach(block => {
        if (block.visible && ballBlockCollision(ball, {
          x: block.x,
          y: block.y,
          width: block.width,
          height: block.height,
          hp: block.hp
        })) {
          block.hp--;
          createExplosion(ball.x, ball.y, block.color); // 產生爆炸粒子
          GameUtils.Audio.play(SOUND_HIT); // 播放擊中音效
          if (block.hp <= 0) {
            block.visible = false;
            gameState.score += 10; // 擊碎一塊磚加10分
            GameUtils.Audio.play(SOUND_BREAK); // 播放磚塊消失音效
          }
        }
      });
    } else if (typeof ball.targetX === 'number') {
      // 橫向滾動歸位
      const speed = 18 * gameState.scale; // 回收速度提升3倍
      if (Math.abs(ball.x - ball.targetX) > 1) {
        if (ball.x < ball.targetX) {
          ball.x = Math.min(ball.x + speed, ball.targetX);
        } else if (ball.x > ball.targetX) {
          ball.x = Math.max(ball.x - speed, ball.targetX);
        }
        ball.y = gameState.canvas.height - gameState.ballRadius;
      }
      // 到達目標點後才算回收
      if (Math.abs(ball.x - ball.targetX) <= 1 && !ball._returned) {
        ball.x = ball.targetX;
        delete ball.targetX;
        gameState.ballsReturned++;
        ball._returned = true;
      }
    }
  });
  // 全部小球回收後，重置歸位點
  if (!gameState.fireReady && gameState.ballsReturned === gameState.balls.length) {
    gameState.isFastForward = false;
    gameState.firePos.x = gameState.nextFireX || gameState.firePos.x;
    gameState.nextFireX = null;
    nextRound();
  }
  // 判斷是否有方塊觸及失敗線
  if (gameState.gameRunning) {
    for (const block of gameState.blocks) {
      if (block.visible && block.y + block.height >= FAIL_LINE_Y()) {
        gameOver();
        break;
      }
    }
  }
}

// 遊戲循環
function gameLoop() {
  if (!gameState.gameRunning) return;
  
  updateGame(); // 更新遊戲狀態
  renderGame(); // 渲染遊戲畫面
  
  requestAnimationFrame(gameLoop);
}

// 渲染遊戲畫面（多球、磚塊數字、瞄準線）
function renderGame() {
  gameState.ctx.clearRect(0, 0, gameState.canvas.width, gameState.canvas.height);

  // 繪製所有小球
  gameState.balls.forEach(ball => {
    gameState.ctx.beginPath();
    gameState.ctx.arc(ball.x, ball.y, gameState.ballRadius, 0, Math.PI * 2);
    gameState.ctx.fillStyle = ball.color;
    gameState.ctx.fill();
    gameState.ctx.closePath();
  });

  // 繪製磚塊及其數字
  gameState.blocks.forEach(block => {
    if (block.visible) {
      gameState.ctx.fillStyle = block.color;
      gameState.ctx.fillRect(block.x, block.y, block.width, block.height);
      // 磚塊邊框
      gameState.ctx.strokeStyle = '#34495E';
      gameState.ctx.lineWidth = 2;
      gameState.ctx.strokeRect(block.x, block.y, block.width, block.height);
      // 磚塊中央顯示生命值數字
      gameState.ctx.fillStyle = '#222222';
      gameState.ctx.font = 'bold 18px Arial';
      gameState.ctx.textAlign = 'center';
      gameState.ctx.textBaseline = 'middle';
      gameState.ctx.fillText(block.hp, block.x + block.width / 2, block.y + block.height / 2);
    }
  });

  // 繪製虛線瞄準線
  if (gameState.isAiming && gameState.aimStart && gameState.aimEnd) {
    gameState.ctx.save();
    gameState.ctx.strokeStyle = '#FFD700';
    gameState.ctx.lineWidth = 2;
    gameState.ctx.setLineDash([8, 8]);
    gameState.ctx.beginPath();
    // 從發射點畫到拖動方向
    gameState.ctx.moveTo(gameState.firePos.x, gameState.firePos.y);
    const dx = gameState.aimEnd.x - gameState.aimStart.x;
    const dy = gameState.aimEnd.y - gameState.aimStart.y;
    // 拉長瞄準線（方便操作）
    const len = 120;
    const angle = Math.atan2(dy, dx);
    const endX = gameState.firePos.x + Math.cos(angle) * len;
    const endY = gameState.firePos.y + Math.sin(angle) * len;
    gameState.ctx.lineTo(endX, endY);
    gameState.ctx.stroke();
    gameState.ctx.setLineDash([]);
    gameState.ctx.restore();
  }

  // 繪製分數和生命值
  gameState.ctx.fillStyle = '#FFFFFF';
  gameState.ctx.font = `${20 * gameState.scale}px Arial`;
  gameState.ctx.textAlign = 'left';
  gameState.ctx.textBaseline = 'top';
  gameState.ctx.fillText(`分數: ${gameState.score}`, 10, 10);
  gameState.ctx.fillText(`球數: ${gameState.ballsToFire}`, 10, 40);
  // 渲染粒子特效
  updateParticles(gameState.ctx);
  // 左下角僅顯示小球圖標與數量
  const padding = 16 * gameState.scale;
  const baseY = gameState.canvas.height - padding;
  gameState.ctx.save();
  // 畫紅色小球
  const ballRadius = 8 * gameState.scale;
  const ballY = baseY - 2 * ballRadius;
  gameState.ctx.beginPath();
  gameState.ctx.arc(padding + ballRadius, ballY, ballRadius, 0, Math.PI * 2);
  gameState.ctx.fillStyle = '#FF6666';
  gameState.ctx.fill();
  // 顯示 xN
  gameState.ctx.fillStyle = '#FFD700';
  gameState.ctx.font = `${16 * gameState.scale}px Arial`;
  gameState.ctx.textAlign = 'left';
  gameState.ctx.textBaseline = 'middle';
  gameState.ctx.fillText(`x${gameState.balls.length}`, padding + ballRadius * 2 + 6 * gameState.scale, ballY);
  gameState.ctx.restore();

  // 底部虛線（失敗線）
  gameState.ctx.save();
  gameState.ctx.strokeStyle = '#FF6666';
  gameState.ctx.lineWidth = 2;
  gameState.ctx.setLineDash([10 * gameState.scale, 8 * gameState.scale]);
  gameState.ctx.beginPath();
  gameState.ctx.moveTo(0, FAIL_LINE_Y());
  gameState.ctx.lineTo(gameState.canvas.width, FAIL_LINE_Y());
  gameState.ctx.stroke();
  gameState.ctx.setLineDash([]);
  gameState.ctx.restore();
}

// 優化 initBlocks，遊戲開始時生成完整貓臉
function initBlocks() {
  gameState.blocks = [];
  const template = CAT_FACE_TEMPLATE;
  const tRows = template.length;
  const tCols = template[0].length;
  // 計算最大可用寬度
  const totalPadding = gameState.canvas.width * 0.08; // 兩側預留4%間距
  const availableWidth = gameState.canvas.width - totalPadding;
  // 原本正方形邊長
  const blockSizeRaw = (availableWidth - (tCols - 1) * (availableWidth * 0.02 / (tCols - 1))) / tCols;
  // 縮小為1/3再放大20%
  const blockSize = blockSizeRaw / 3 * 1.2;
  const blockPadding = blockSize * 0.25; // 間距也隨之調整
  const startX = (gameState.canvas.width - (blockSize * tCols + blockPadding * (tCols - 1))) / 2;
  const colors = ['#FF6B6B', '#4ECDC4', '#45B7D1', '#96CEB4', '#FFEAA7'];
  for (let row = 0; row < tRows; row++) {
    for (let col = 0; col < tCols; col++) {
      if (template[row][col] === 1) {
        const x = startX + col * (blockSize + blockPadding);
        const y = row * (blockSize + blockPadding) + 50 * gameState.scale;
        // 隨機生成磚塊生命值（1~5）
        const hp = GameUtils.randomInt(1, 5);
        gameState.blocks.push({
          x: x,
          y: y,
          width: blockSize,
          height: blockSize,
          color: colors[row % colors.length],
          visible: true,
          hp: hp
        });
      }
    }
  }
  // 更新全局磚塊尺寸，供碰撞和渲染用
  gameState.blockWidth = blockSize;
  gameState.blockHeight = blockSize;
  gameState.blockPadding = blockPadding;
}

// 下一回合
function nextRound() {
  // 判斷是否進入難度關卡
  const isAnimalStage = (gameState.ballsToFire > 0 && gameState.ballsToFire % 6 === 0);
  if (isAnimalStage) {
    // 隨機選一個動物模板
    const animal = ANIMAL_TEMPLATES[Math.floor(Math.random() * ANIMAL_TEMPLATES.length)];
    const tRows = animal.length;
    const tCols = animal[0].length;
    const blockSize = gameState.blockWidth;
    const blockPadding = gameState.blockPadding;
    const startX = (gameState.canvas.width - (blockSize * tCols + blockPadding * (tCols - 1))) / 2;
    const startY = 50 * gameState.scale;
    const colors = ['#FF6B6B', '#4ECDC4', '#45B7D1', '#96CEB4', '#FFEAA7'];
    // 先將現有方塊全部下移到動物圖形下方
    const moveY = (blockSize + blockPadding) * tRows;
    gameState.blocks.forEach(block => {
      block.y += moveY;
    });
    // 生成佔用格子表
    const gridMap = getOccupiedGridMap(gameState.blocks, tRows, tCols, blockSize, blockPadding, startX, startY);
    // 在頂部完整生成動物圖形（避免重疊）
    for (let row = 0; row < tRows; row++) {
      for (let col = 0; col < tCols; col++) {
        if (animal[row][col] === 1 && !isGridOccupied(row, col, gridMap)) {
          const x = startX + col * (blockSize + blockPadding);
          const y = startY + row * (blockSize + blockPadding);
          // 新增難度：每回合新方塊血量基礎值增加 1-10
          const hp = GameUtils.randomInt(2, 7 + Math.floor(gameState.ballsToFire / 2)) + GameUtils.randomInt(1, 10);
          gameState.blocks.push({
            x: x,
            y: y,
            width: blockSize,
            height: blockSize,
            color: colors[row % colors.length],
            visible: true,
            hp: hp
          });
        }
      }
    }
  } else {
    // 所有磚塊下移一行
    const moveY = gameState.blockHeight + gameState.blockPadding;
    gameState.blocks.forEach(block => {
      block.y += moveY;
      // 若有磚塊到達底部，遊戲結束
      if (block.visible && block.y + block.height >= FAIL_LINE_Y()) {
        gameOver();
      }
    });
    // 只在頂部新增一行隨機方塊（避免重疊）
    const tCols = CAT_FACE_TEMPLATE[0].length;
    const blockSize = gameState.blockWidth;
    const blockPadding = gameState.blockPadding;
    const startX = (gameState.canvas.width - (blockSize * tCols + blockPadding * (tCols - 1))) / 2;
    const startY = 50 * gameState.scale;
    const colors = ['#FF6B6B', '#4ECDC4', '#45B7D1', '#96CEB4', '#FFEAA7'];
    // 生成佔用格子表
    const gridMap = getOccupiedGridMap(gameState.blocks, 1, tCols, blockSize, blockPadding, startX, startY);
    for (let col = 0; col < tCols; col++) {
      if (Math.random() < 0.7 && !isGridOccupied(0, col, gridMap)) {
        const x = startX + col * (blockSize + blockPadding);
        const y = startY;
        // 新增難度：每回合新方塊血量基礎值增加 1-10
        const hp = GameUtils.randomInt(1, 5 + Math.floor(gameState.ballsToFire / 2)) + GameUtils.randomInt(1, 10);
        gameState.blocks.push({
          x: x,
          y: y,
          width: blockSize,
          height: blockSize,
          color: colors[col % colors.length],
          visible: true,
          hp: hp
        });
      }
    }
  }
  // 新增一顆球（每回合+1）
  gameState.ballsToFire++;
  resetBalls();
  gameState.fireReady = true;
  gameState.ballsReturned = 0;
  console.log(`進入第 ${gameState.ballsToFire} 回合`);
}

// 遊戲結束
function gameOver() {
  gameState.gameRunning = false;
  GameUtils.Audio.play(SOUND_FAIL); // 播放失敗音效
  // 更新最高分
  if (gameState.score > getBestScore()) {
    setBestScore(gameState.score);
  }
  console.log('遊戲結束！');
}

// 最高分存取（兼容微信和瀏覽器）
function getBestScore() {
  if (typeof wx !== 'undefined' && wx.getStorageSync) {
    return Number(wx.getStorageSync(BEST_SCORE_KEY) || 0);
  } else if (typeof localStorage !== 'undefined') {
    return Number(localStorage.getItem(BEST_SCORE_KEY) || 0);
  } else {
    return 0;
  }
}
function setBestScore(score) {
  if (typeof wx !== 'undefined' && wx.setStorageSync) {
    wx.setStorageSync(BEST_SCORE_KEY, score);
  } else if (typeof localStorage !== 'undefined') {
    localStorage.setItem(BEST_SCORE_KEY, score);
  }
}

// 主函數
function main() {
  initGame();
  gameLoop();
}

main();